home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 February
/
EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso
/
earcd
/
util4
/
cy.lha
/
cy
next >
Wrap
Text File
|
1996-01-10
|
18KB
|
721 lines
/*
* cy Copyright © 1995 by Rick Younie
*
* $VER: v1.1 Thu Jan 4 1996
* rick@emma.panam.wimsey.com
* rick@freenet.vancouver.bc.ca
*
* USAGE: '?' for usage
*
* SYNOPSIS:
* - CyberCron management program
*
*/
signal on BREAK_C
signal on HALT
/*---------------- USER SETTABLE OPTIONS (begin) ------------------------*/
screenwidth = 640
screenheight = 200
editor = 'C:ed -sticky' /* editor must hang on to CLI */
CyberCron = 'ME:Tools/CyberCron' /* path+name of CC program */
crontab = 'SYS:S/CronTab'
sendmail = '"sendmail -f %s -R *"%s*""'
startcmd = CyberCron 'CRONTAB' crontab 'SENDMAIL' sendmail
logfile = 'LOGS:CyberCron.log'
/*---------------- USER SETTABLE OPTIONS (end) --------------------------*/
lf = '0a'x
cr = '0d'x
crlf = cr || lf
csi = '9b'x
font = 8
rows = screenheight % font - 2
cols = screenwidth % font - 1
/* -------------------------------------------------------------------
*
*/
Main:
address 'CYBERCRON'
options results
options failat 99
parse arg option
select
when option = '-n' then call NextEvent
when option = '-l' then call ListEventsSorted
when option = '-L' then call ListEvents
when option = '-e' then call Edit
when option = '-b' then call StartCyber
when option = '-q' | option = '-k' then call KillCyber
when option = '-s'
then if Suspend_Resume('SUSPEND') then say ShowStatus()
when option = '-r'
then if Suspend_Resume('RESUME') then say ShowStatus()
when option = '-g' then call ToggleLog
when option = '' then call RawStuff
otherwise Call Usage
end
exit 0
/*####################################################################
## raw window ##
####################################################################*/
/* -----------------------------------------------------------------*/
RawStuff:
cursorUp = '41'x
cursorDown = '42'x
cursorRight = '43'x
cursorLeft = '44'x
if ~Running()
then call ErX "..CyberCron not running - 'cy ?' for Usage"
call MakeRaw
Refresh:
call WriteSkel /* write header,footer */
ReScan:
numevents = ReadEvents() /* get all queued events from CC */
if numevents = 0 then page = 0
else page = 1
row = 1
itemsPerPage = rows - 8
itemsLastPage = numevents // itemsPerPage
maxpage = numevents % itemsPerPage + (itemsLastPage~=0)
items. = itemsPerPage
items.0 = 1
if itemsLastPage = 0 then items.maxpage = itemsPerPage
else items.maxpage = itemsLastPage
if numevents~=0 then call WritePage
else call WriteSkel
/*
* we spend most of our time here, handling keystrokes
*/
do forever
oldpos = row
char = readch('STDIN', 1)
select
/* handle cursor keys */
when char = '9b'x then do
char = readch('STDIN', 1)
select
when numevents=0 then nop
when char = cursorDown then do
row = row + 1
if row > items.page then row = 1
call MoveCursor
end
when char = cursorUp then do
row = row - 1
if row = 0 then row = items.page
call MoveCursor
end
when char = cursorRight then do
if page ~= maxpage then do
page = page + 1
call WritePage
end
end
when char = cursorLeft then do
if page > 1 then do
page = page - 1
call WritePage
end
end
otherwise nop
end
end /* cursor keys */
/* not a cursor key */
otherwise do
select
when char = 's'
then if Suspend_Resume('SUSPEND') then call WriteStatus
when char = 'r'
then if Suspend_Resume('RESUME') then call WriteStatus
when char = 'a' then call AddEvent('NORM')
when char = 'A' then call AddEvent('CC')
when char = 'e' then call EditCrontab
when char = 'n' then signal Refresh /* ReScan? */
when char = 'q' then do
if Quit() then leave
call MsgAndDelay '..quit aborted'
end
when char = 'Q' then leave
when char = 'g' then call ToggleLogFile
/* dont allow the following options if no events */
when numevents = 0 then nop
when char = 't' then do
tmp = (page-1)*itemsPerPage + row
tag.tmp = (tag.tmp=0) /* toggle flag */
if tag.tmp then star = '*'
else star = ' '
call writech 'STDOUT',csi || row+2';3H'star
row = row + 1
if row > items.page then row = 1
call MoveCursor
end
/* space bar follows Tin behavior
* >1 page?
* - if ~last page, go to next
* - else if not at end of page, go to end
* - else go to first page
* =1 page; if not at bottom, go there
* else go to top
*/
when char = ' ' then do
if maxpage > 1 then do
if page ~= maxpage then do
page = page + 1
call WritePage
end
else do
if row ~= items.page then do
row = items.page
call MoveCursor
end
else do
page = 1
call WritePage
end
end
end
else do /* only 1 page; go to bot/top */
if row = items.page then row = 1
else row = items.page
call MoveCursor
end
end
when char = 'd' then call DeleteEvent
when char = 'p' then call PurgeRexx
otherwise nop
end
end
end /* select */
call PrintTime
end /* forever */
exit 0
MoveCursor:
call writech 'STDOUT', csi || oldpos+2';1H '
call writech 'STDOUT', csi || row+2';1H->' || csi || rows';1H'
return
CLineMsg:
call writech 'STDOUT', csi || rows';1H'csi'K 'arg(1) || cr
return
/* -------------------------------------------------------------------
*
*/
WriteSkel:
prompt.1 = '[s]uspend [r]esume [t]ag [d]elete [e]dit_crontab resca[n] lo[g]_file'
prompt.2 = '<=prev page (spacebar) next page=> [aA]dd [qQ]uit [p]urge_rexx_events'
'VERSION'
title = '-- cy -- [CyberCron' word(result,1)']'
call writech 'STDOUT', csi'H'csi'J' || center(title,cols) || crlf
call writech 'STDOUT', csi || rows - 4';1H'center(prompt.1,cols)
call writech 'STDOUT', csi || rows - 3';1H'center(prompt.2,cols)
WriteStatus:
call writech 'STDOUT', csi || rows - 2';1H'center(ShowStatus(),cols)
call CLineMsg ''
PrintTime:
call writech 'STDOUT', csi || '1;4H'time()' 'date('E') || csi || rows';1H'
return
/* ------------------------------------------------------------------- */
WritePage:
tmp = right('p'page 'of' maxpage,10)
call writech 'STDOUT', csi || '1;'cols-length(tmp)'H'tmp
offset = (page-1)*itemsPerPage /* offset into event.i */
/* write this pages events to window */
do i = 1 to items.page
tmp = offset + i
if tag.tmp then star = '*'
else star = ' '
call writech 'STDOUT', csi || i+2';1H'csi'K 'star || event.tmp || crlf
end i
/* clear leftover lines */
do i = items.page+1 to itemsPerPage + 1
call writech 'STDOUT', csi || i+2';1H'csi'K'
end i
/* reset to first entry whenever page is redrawn */
row = 1
call writech 'STDOUT', csi || row+2';1H->'
WipeBottom2:
/* wipe 2 command lines, positions cursor at bottom */
call writech 'STDOUT', csi || rows-1';1H'csi'J'csi || rows';1H'
signal PrintTime
/* ----------------------------------------------------------------
* ssc_id.i = 12345678'ext' 12345678 0x12345678 for the sort
* - ext=ext+1 for every CC event read so :OBEYQUEUE-type
* events dont get mixed up by the sort
* - shifted to just 'ssc id' after the sort
* event.i = time date event_to_execute
*/
ReadEvents:
tag. = 0 /* clear tags on a new read */
/* get all events in CC-id format */
'LIST_EVENTS'
list = result
if left(list,2)~='0x' then ssc_id.0 = 0 /* no events queued */
else do
if option = '' then call CLineMsg '..getting events'
/* fill 'sssc.ext sssc 0x' array for sort */
ssc_id.0 = words(list)
do i = 1 to ssc_id.0
/* get time for its next execution */
id = word(list,i)
'EVENT_NEXT_EXEC' id
ssc = result
if ssc = '' then tmp = 0 /* could not be found */
tmp = ssc || right('0'i,2) /* 01,02..added to events
so QUEUE events of same time dont scramble */
ssc_id.i = tmp ssc id
end i
if option = '' then call CLineMsg '..sorting'
/* one of Knuth's sort algorithms
- rony@wu-wien.ac.at (Rony G. Flatscher) */
m = 1
do while (9 * m + 4) < ssc_id.0
m = m * 3 + 1
end
do while m > 0
k = ssc_id.0 - M
do j = 1 to k
q = j
do while q > 0
l = q + m
if ssc_id.q <= ssc_id.l then leave
/* switch elements */
tmp = ssc_id.q
ssc_id.q = ssc_id.l
ssc_id.l = tmp
q = q - m
end
end
m = m % 3
end /* sort */
if option = '' then call CLineMsg '..converting'
/* now fill event.i with events sorted as to time */
today = date('E')
scnwidth = cols - 4
do i = 1 to ssc_id.0
parse var ssc_id.i . ssc id
/* lose the ssc+extension variable to save a little confusion */
ssc_id.i = ssc id
'SHOW_EVENT' id
event.i = subword(result,7) /* the event */
'EXPAND_SSSC' ssc
parse var result . min hr day mon yr .
date = right('00'day,2)'/'right('00'mon,2)'/'right(yr,2)
if date = today then date = ' '
/* truncate for screen */
event.i = right('00'hr,2)':'right('00'min,2) date event.i
if length(event.i) > scnwidth then event.i = left(event.i,scnwidth)
end i
end
return ssc_id.0
/* -------------------------------------------------------------------
*
*/
PurgeRexx:
call CLineMsg 'delete rexx events? y/n'
char = readch('STDIN',1)
if upper(char)='Y' then do
'PURGE_REXX_EVENTS' /* no RC? */
call MsgAndDelay '..rexx events purged'
end
else call MsgAndDelay '..purge aborted'
signal ReScan
/* -------------------------------------------------------------------
*
*/
ToggleLogFile:
if right(ShowStatus(),2) = 'ON' then 'CLOSE_LOG_FILE'
else 'NEW_LOG_FILE' logfile
if RC ~= 0 then call MsgAndDelay '..error toggling' logfile
signal WriteStatus
return
/* -------------------------------------------------------------------
*
*/
EditCrontab:
if Edit()~=0 then do
call CLineMsg '..editor under USER SETTABLE OPTIONS set incorrectly?',
' <ret> to continue'
call readch 'STDIN', 1
signal Refresh /* dos can mess up window with err msg */
end
signal ReScan
Edit:
address 'COMMAND' editor crontab
return RC
/* -------------------------------------------------------------------
* NORM = hh:mm event
* CC = min hour day month dow(Sun=0) event
*/
AddEvent:
parse arg type
prompt.NORM = 'hh:mm'
prompt.CC = 'min hr day mon dow(Sun=0)'
prompt = csi || rows-1';1H'csi'K'prompt.type' event'csi || rows';1H'
do forever
call writech 'STDOUT',prompt
string = GetEvent()
if string = '' then do
call MsgAndDelay '..aborting - no add'
signal WipeBottom2
end
if type = 'NORM' then do
once = ''
parse var string hr ':' min event
event = strip(event)
if abbrev(string,'*:*')
then once = ':EXECONCE'
string = min hr '* * *' once event
end
'ADD_EVENT' string
/* event was added ok - go get new lineup from CC */
if RC=0 then do
call MsgAndDelay 'ok'
signal ReScan
end
else do /* not added - try again */
call writech 'STDOUT', csi || rows-1';33H **error** [ <ret> to continue ]'
call readch 'STDIN', 1
call writech 'STDOUT', csi || rows-1';1H'csi'J'csi || rows
end
end
return
/* ----------------handle user add_event input---------------------- */
GetEvent:
string = ''
do forever
char = readch('STDIN',1)
select
when char > '1f'x & char < '7f'x then do
if length(string) <= cols-2 then string = string || char
else char = '07'x
call writech 'STDOUT',char
end
/* delete a character */
when char = '08'x then do
if string ~== '' then do
string = substr(string,1,length(string)-1)
call writech 'STDOUT', csi'D'csi'P'
end
end
/* done */
when char = cr then break
/* discard cursor key 2nd byte */
when char = csi then call readch 'STDIN',1
otherwise nop
end
end
return string
/* -------------------------------------------------------------------
* Delete all tagged events; else current event
*/
DeleteEvent:
/* any tagged for delete? */
tagged = 0
do i = 1 to numevents
tagged = tagged + tag.i
end i
/* got tagged event(s) */
if tagged > 0 then do
call CLineMsg 'delete' tagged 'tagged event'copies('s',tagged~=1)'? y/n '
char = readch('STDIN',1)
if upper(char)~='Y' then break
do i = 1 to numevents
if tag.i then call DeleteOne word(ssc_id.i,2)
end
signal ReScan
end
/* delete current event? */
call CLineMsg 'delete this event? y/n '
char = readch('STDIN',1)
if upper(char)~='Y' then call MsgAndDelay '..aborting - no delete'
else do
tmp = (page-1)*itemsPerPage+row
call DeleteOne word(ssc_id.tmp,2)
signal ReScan
end
return
DeleteOne:
parse arg id
call CLineMsg '..deleting'
'DELETE_EVENT' id
if RC~=0 then call MsgAndDelay '..couldn''t find event'
return
/* ------ write a message to command line, wait, then wipe it ----- */
MsgAndDelay:
parse arg msg
call CLineMsg msg
call delay 25
call CLineMsg ''
return
/* -------------------------------------------------------------------
*
*/
Quit:
parse value ShowStatus() with ':' status .
if status = 'ACTIVE' then statusprompt = ''
else statusprompt = '..CC suspended'
call CLineMsg statusprompt'..really quit? y/n '
char = readch('STDIN',1)
return upper(char)='Y'
/*####################################################################
## do command line requests ##
####################################################################*/
/* -----------------------------------------------------------------*/
ListEventsSorted:
if ~Running() then say '..CyberCron isn''t running'
else do
num_events = ReadEvents()
if numevents = 0 then say '..no events queued'
else do i = 1 to num_events
say event.i
end i
say ' 'ShowStatus()
end
return
/* -----------------------------------------------------------------*/
ListEvents:
if ~Running() then say '..CyberCron isn''t running'
else do
'LIST_EVENTS'
list = result
if left(list,2)~='0x' then say '..no events queued'
else do i = 1 to words(list)
'SHOW_EVENT' word(list,i)
say subword(result,2)
end
say ' 'ShowStatus()
end
return
/* -----------------------------------------------------------------*/
NextEvent:
if ~Running() then say '..CyberCron isn''t running'
else do
numevents = ReadEvents()
if numevents = 0 then say '..no events queued'
else do
lasttime = word(ssc_id.1,1) /* show all events queued for next time */
do i = 1 to numevents
thistime = word(ssc_id.i,1)
if thistime ~= lasttime then break
id = word(ssc_id.i,2)
say event.i
lasttime = thistime
end i
say ' 'ShowStatus()
end
end
return
/* ------------------------------------------------------------- */
Suspend_Resume:
running = Running()
if ~running then say '..CyberCron isn''t running'
else ''arg(1)''
return running
/* ------------------------------------------------------------- */
ShowStatus: PROCEDURE
'SHOW_STATUS'
parse var result activity ' "' ctab '" "' lfile '"'
star = copies('*',activity='SUSPENDED')
if lfile = '<None>' then tmp = 'OFF'
else tmp = 'ON'
return 'Status:'star||activity||star 'Crontab='ctab 'Log='tmp
/* ------------------------------------------------------------- */
KillCyber:
if ~Running() then say '..CyberCron isn''t running'
else do
'QUIT'
do i = 1 to 10
call delay 25
if ~Running() then break
end i
if i <= 10 then say '..CyberCron is dead'
else say '..CyberCron will quit after the current job is finished'
end
return
/* ------------------------------------------------------------- */
StartCyber:
if Running() then say '..CyberCron is already running'
else do
address 'COMMAND' 'run >NIL: <NIL:' startcmd
do i = 1 to 10
call delay 25
if Running() then break
end i
if i <= 10 then say '..CyberCron started'
else say '..couldn''t start' CyberCron || lf ||,
' path set incorrectly under USER SETTABLE OPTIONS?'
end
return
/* ------ 0=not running; 1=running ------------------------------ */
Running:
return show('PORT','CYBERCRON')
/* ----------------------------------------------------------------
* no useful RC for illegal logfile, so ignore
*/
ToggleLog: PROCEDURE EXPOSE logfile
if ~Running() then say '..CyberCron isn''t running'
else do
'SHOW_STATUS'
parse var result . . logstat
if logstat = '"<None>"' then do
call writech 'STDOUT', ' Logfile is OFF; turn it ON? Y/n '
char = readln('STDIN')
if upper(char) ~= 'N' then do
'NEW_LOG_FILE' logfile
say '..'logfile 'turned ON'
end
else say '..aborted'
end
else do
call writech 'STDOUT', ' Logfile is ON; turn it OFF? Y/n '
char = readln('STDIN')
if upper(char) ~= 'N' then do
'CLOSE_LOG_FILE'
say '..'logfile 'turned OFF'
end
else say '..aborted'
end
end
return
/* ---------------------------------------------------------------- */
MakeRaw:
call close 'STDOUT'
call close 'STDIN'
call open 'STDOUT','RAW:0/0/'screenwidth'/'screenheight'//NOSIZE'
call pragma '*','STDOUT'
call open 'STDIN','*'
return
/* ---------------------------------------------------------------- */
Usage:
say 'Usage: cy -option'
say ' -e edit crontab ['editor crontab']'
say ' -b begin CyberCron ['CyberCron']'
say ' -q quit (kill) CyberCron'
say ' -s suspend'
say ' -r resume'
say ' -n next event(s) to execute'
say ' -l list all events, sorted'
say ' -L list all events, raw'
say ' -g toggle the logfile ['logfile']'
say ' no option is the most fun'
say ' editor =' editor
say ' logfile =' logfile
say ' crontab =' crontab
exit 0
ErX:
say arg(1)
HALT:
BREAK_C:
exit 10